home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / MBUF.C < prev    next >
C/C++ Source or Header  |  1988-07-28  |  7KB  |  412 lines

  1. /* Primitive mbuf allocate/free routines */
  2.  
  3. #include "global.h"
  4. #include "mbuf.h"
  5.  
  6. /* Allocate mbuf with associated buffer of 'size' bytes */
  7. struct mbuf *
  8. alloc_mbuf(size)
  9. register int16 size;
  10. {
  11.     register struct mbuf *bp;
  12.  
  13.     if((bp = (struct mbuf *)malloc((unsigned)(size + sizeof(struct mbuf)))) == NULLBUF)
  14.         return NULLBUF;
  15.     bp->next = bp->anext = NULLBUF;
  16.     if(size != 0){
  17.         bp->data = (char *)(bp + 1);
  18.     } else {
  19.         bp->data = NULLCHAR;
  20.     }
  21.     bp->cnt = 0;
  22.     return bp;
  23. }
  24.  
  25. /* Free all resources associated with mbuf
  26.  * Return pointer to next mbuf in packet chain
  27.  */
  28. struct mbuf *
  29. free_mbuf(bp)
  30. register struct mbuf *bp;
  31. {
  32.     register struct mbuf *bp1 = NULLBUF;
  33.  
  34.     if(bp != NULLBUF){
  35.         bp1 = bp->next;
  36.         free((char *)bp);
  37.     }
  38.     return bp1;
  39. }
  40.  
  41. /* Free packet (a chain of mbufs). Return pointer to next packet on queue,
  42.  * if any
  43.  */
  44. struct mbuf *
  45. free_p(bp)
  46. register struct mbuf *bp;
  47. {
  48.     struct mbuf *abp;
  49.  
  50.     if(bp == NULLBUF)
  51.         return NULLBUF;
  52.     abp = bp->anext;
  53.     while(bp != NULLBUF)
  54.         bp = free_mbuf(bp);
  55.     return abp;
  56. }        
  57. /* Free entire queue of packets (of mbufs) */
  58. free_q(q)
  59. struct mbuf **q;
  60. {
  61.     register struct mbuf *bp;
  62.  
  63.     while((bp = dequeue(q)) != NULLBUF)
  64.         free_p(bp);
  65. }
  66.  
  67. /* Count up the total number of bytes in an mbuf */
  68. int16
  69. len_mbuf(bp)
  70. register struct mbuf *bp;
  71. {
  72.     int cnt;
  73.  
  74.     cnt = 0;
  75.     while(bp != NULLBUF){
  76.         cnt += bp->cnt;
  77.         bp = bp->next;
  78.     }
  79.     return cnt;
  80. }
  81. /* Count up the number of packets in a queue */
  82. int16
  83. len_q(bp)
  84. register struct mbuf *bp;
  85. {
  86.     register int cnt;
  87.  
  88.     for(cnt=0;bp != NULLBUF;cnt++,bp = bp->anext)
  89.         ;
  90.     return cnt;
  91. }
  92. /* Trim mbuf to specified length by lopping off end */
  93. trim_mbuf(bpp,length)
  94. struct mbuf **bpp;
  95. int16 length;
  96. {
  97.     register int16 tot = 0;
  98.     register struct mbuf *bp;
  99.  
  100.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  101.         return;    /* Nothing to trim */
  102.  
  103.     if(length == 0){
  104.         /* Toss the whole thing */
  105.         free_p(*bpp);
  106.         *bpp = NULLBUF;
  107.         return;
  108.     }
  109.     /* Find the point at which to trim. If length is greater than
  110.      * the packet, we'll just fall through without doing anything
  111.      */
  112.     for( bp = *bpp; bp != NULLBUF; bp = bp->next){
  113.         if(tot + bp->cnt < length){
  114.             tot += bp->cnt;
  115.         } else {
  116.             /* Cut here */
  117.             bp->cnt = length - tot;
  118.             free_p(bp->next);
  119.             bp->next = NULLBUF;
  120.             break;
  121.         }
  122.     }
  123. }
  124. /* Duplicate/enqueue/dequeue operations based on mbufs */
  125.  
  126. /* Duplicate first 'cnt' bytes of packet starting at 'offset'.
  127.  * This is done without copying data; only the headers are duplicated,
  128.  * but without data segments of their own. The pointers are set up to
  129.  * share the data segments of the original copy. The return pointer is
  130.  * passed back through the first argument, and the return value is the
  131.  * number of bytes actually duplicated.
  132.  */
  133. int16
  134. dup_p(hp,bp,offset,cnt)
  135. struct mbuf **hp;
  136. register struct mbuf *bp;
  137. register int16 offset;
  138. register int16 cnt;
  139. {
  140.     register struct mbuf *cp;
  141.     int16 tot;
  142.  
  143.     if(cnt == 0 || bp == NULLBUF || hp == NULLBUFP){
  144.         if(hp != NULLBUFP)
  145.             *hp = NULLBUF;
  146.         return 0;
  147.     }
  148.     if((*hp = cp = alloc_mbuf(0)) == NULLBUF){
  149.         return 0;
  150.     }
  151.     /* Skip over leading mbufs that are smaller than the offset */
  152.     while(bp != NULLBUF && bp->cnt <= offset){
  153.         offset -= bp->cnt;
  154.         bp = bp->next;
  155.     }
  156.     if(bp == NULLBUF){
  157.         free_mbuf(cp);
  158.         *hp = NULLBUF;
  159.         return 0;    /* Offset was too big */
  160.     }
  161.     tot = 0;
  162.     for(;;){
  163.         cp->data = bp->data + offset;
  164.         cp->cnt = min(cnt,bp->cnt - offset);
  165.         offset = 0;
  166.         cnt -= cp->cnt;
  167.         tot += cp->cnt;
  168.         bp = bp->next;
  169.         if(cnt == 0 || bp == NULLBUF || (cp->next = alloc_mbuf(0)) == NULLBUF)
  170.             break;
  171.         cp = cp->next;
  172.     }
  173.     return tot;
  174. }
  175. /* Copy first 'cnt' bytes of packet into a new, single mbuf */
  176. struct mbuf *
  177. copy_p(bp,cnt)
  178. register struct mbuf *bp;
  179. register int16 cnt;
  180. {
  181.     register struct mbuf *cp;
  182.     register char *wp;
  183.     register int16 n;
  184.  
  185.     if(bp == NULLBUF || cnt == 0 || (cp = alloc_mbuf(cnt)) == NULLBUF)
  186.         return NULLBUF;
  187.     wp = cp->data;
  188.     while(cnt != 0 && bp != NULLBUF){
  189.         n = min(cnt,bp->cnt);
  190.         memcpy(wp,bp->data,n);
  191.         wp += n;
  192.         cp->cnt += n;
  193.         cnt -= n;
  194.         bp = bp->next;
  195.     }
  196.     return cp;
  197. }
  198. /* Copy and delete "cnt" bytes from beginning of packet. Return number of
  199.  * bytes actually pulled off
  200.  */
  201. int16
  202. pullup(bph,buf,cnt)
  203. struct mbuf **bph;
  204. char *buf;
  205. int16 cnt;
  206. {
  207.     register struct mbuf *bp;
  208.     int16 n,tot;
  209.  
  210.     tot = 0;
  211.     if(bph == NULLBUFP)
  212.         return 0;
  213.     while(*bph != NULLBUF && cnt != 0){
  214.         bp = *bph;
  215.         n = min(cnt,bp->cnt);
  216.         if(buf != NULLCHAR && n != 0){
  217.             memcpy(buf,bp->data,n);
  218.             buf += n;
  219.         }
  220.         tot += n;
  221.         cnt -= n;
  222.         bp->data += n;
  223.         bp->cnt -= n;        
  224.         if(bp->cnt == 0){
  225.             *bph = free_mbuf(bp);
  226.         }
  227.     }
  228.     return tot;
  229. }
  230. /* Append mbuf to end of mbuf chain */
  231. void
  232. append(bph,bp)
  233. struct mbuf **bph;
  234. struct mbuf *bp;
  235. {
  236.     register struct mbuf *p;
  237.  
  238.     if(bph == NULLBUFP || bp == NULLBUF)
  239.         return;
  240.     if(*bph == NULLBUF){
  241.         /* First one on chain */
  242.         *bph = bp;
  243.     } else {
  244.         for(p = *bph ; p->next != NULLBUF ; p = p->next)
  245.             ;
  246.         p->next = bp;
  247.     }
  248. }
  249. /* Append packet to end of packet queue */
  250. void
  251. enqueue(q,bp)
  252. struct mbuf **q;
  253. struct mbuf *bp;
  254. {
  255.     register struct mbuf *p;
  256.     char i_state;
  257.  
  258.     if(q == NULLBUFP || bp == NULLBUF)
  259.         return;
  260.     i_state = disable();
  261.     if(*q == NULLBUF){
  262.         /* List is empty, stick at front */
  263.         *q = bp;
  264.     } else {
  265.         for(p = *q ; p->anext != NULLBUF ; p = p->anext)
  266.             ;
  267.         p->anext = bp;
  268.     }
  269.     restore(i_state);
  270. }
  271. /* Unlink a packet from the head of the queue */
  272. struct mbuf *
  273. dequeue(q)
  274. register struct mbuf **q;
  275. {
  276.     register struct mbuf *bp;
  277.     char i_state;
  278.  
  279.     if(q == NULLBUFP)
  280.         return NULLBUF;
  281.     i_state = disable();
  282.     if((bp = *q) != NULLBUF){
  283.         *q = bp->anext;
  284.         bp->anext = NULLBUF;
  285.     }
  286.     restore(i_state);
  287.     return bp;
  288. }    
  289.  
  290. /* Copy user data into an mbuf */
  291. struct mbuf *
  292. qdata(data,cnt)
  293. char *data;
  294. int16 cnt;
  295. {
  296.     register struct mbuf *bp;
  297.  
  298.     if((bp = alloc_mbuf(cnt)) == NULLBUF)
  299.         return NULLBUF;
  300.     memcpy(bp->data,data,cnt);
  301.     bp->cnt = cnt;
  302.     return bp;
  303. }
  304. /* Copy mbuf data into user buffer */
  305. int16
  306. dqdata(bp,buf,cnt)
  307. struct mbuf *bp;
  308. char *buf;
  309. unsigned cnt;
  310. {
  311.     unsigned n,tot;
  312.     struct mbuf *bp1;
  313.  
  314.     if(buf == NULLCHAR)
  315.         return 0;
  316.     
  317.     tot = 0;
  318.     for(bp1 = bp;bp1 != NULLBUF; bp1 = bp1->next){
  319.         n = min(bp1->cnt,cnt);
  320.         memcpy(buf,bp1->data,n);
  321.         cnt -= n;
  322.         buf += n;
  323.         tot += n;
  324.     }
  325.     free_p(bp);
  326.     return tot;
  327. }
  328. /* Pull a 32-bit integer in host order from buffer in network byte order */
  329. int32
  330. pull32(bpp)
  331. struct mbuf **bpp;
  332. {
  333.     int32 rval;
  334.     char buf[4];
  335.     register char *cp;
  336.  
  337.     if(pullup(bpp,buf,4) != 4){
  338.         /* Return zero if insufficient buffer */
  339.         for(cp = buf;cp < &buf[4];cp++)
  340.             *cp = 0;
  341.     }
  342.     cp = buf;
  343.  
  344.     /* Unwound for speed */
  345.     rval = *cp++ & 0xff;
  346.     rval <<= 8;
  347.     rval |= *cp++ & 0xff;
  348.     rval <<= 8;
  349.     rval |= *cp++ & 0xff;
  350.     rval <<= 8;
  351.     rval |= *cp & 0xff;
  352.  
  353.     return rval;
  354. }
  355. /* Pull a 16-bit integer in host order from buffer in network byte order */
  356. int16
  357. pull16(bpp)
  358. struct mbuf **bpp;
  359. {
  360.     int16 rval;
  361.     char buf[2];
  362.     register char *cp;
  363.  
  364.     if(pullup(bpp,buf,2) != 2){
  365.         /* Return zero if insufficient buffer */
  366.         for(cp=buf; cp < &buf[2]; cp++)
  367.             *cp = 0;
  368.     }
  369.     cp = buf;
  370.  
  371.     rval = *cp++ & 0xff;
  372.     rval <<= 8;
  373.     rval |= *cp & 0xff;
  374.     return rval;
  375. }
  376. /* Pull single character from mbuf */
  377. char
  378. pullchar(bpp)
  379. struct mbuf **bpp;
  380. {
  381.     char c;
  382.  
  383.     if(pullup(bpp,&c,1) != 1)
  384.         /* Return zero if nothing left */
  385.         c = 0;
  386.     return c;
  387. }
  388. /* Put a long in host order into a char array in network order */
  389. char *
  390. put32(cp,x)
  391. register char *cp;
  392. int32 x;
  393. {
  394.     *cp++ = x >> 24;
  395.     *cp++ = x >> 16;
  396.     *cp++ = x >> 8;
  397.     *cp++ = x;
  398.  
  399.     return cp;
  400. }
  401. /* Put a short in host order into a char array in network order */
  402. char *
  403. put16(cp,x)
  404. register char *cp;
  405. int16 x;
  406. {
  407.     *cp++ = x >> 8;
  408.     *cp++ = x;
  409.  
  410.     return cp;
  411. }
  412.